# Copyright (c) 2024 Huawei Technologies Co., Ltd.
#
# openMind is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#
#          http://license.coscl.org.cn/MulanPSL2
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
from functools import wraps
import os
import time
from typing import Callable, Optional, TypeVar
import unittest
import uuid

import openmind_hub  # noqa: E402
from openmind_hub import AccessWhiteListError  # noqa: E402
from tests.constants import OPENMIND_HUB_ENDPOINT

os.environ["OPENMIND_HUB_ENDPOINT"] = OPENMIND_HUB_ENDPOINT
USER = os.environ.get("HUB_USER")
TOKEN = os.environ.get("HUB_TOKEN")
if not TOKEN:
    raise Exception("Please set HUB_TOKEN environment variable.")

ORGANIZATION = "openmind"

T = TypeVar("T")


def random_repo_name(repo_name: Optional[str] = None, prefix: str = "repo") -> str:
    """
    Return a readable pseudo-unique repository name for tests.

    Example:
    ```py
    >>> random_repo_name()
    repo-2fe93f-16599646671840

    >>> random_repo_name("my-space", prefix='space')
    space-my-space-16599481979701
    """
    if repo_name is None:
        repo_name = uuid.uuid4().hex[:6]
    ts = int(time.time() * 10e3)
    return f"{prefix}-{repo_name}-{ts}"


def use_tmp_repo(owner: str = ORGANIZATION, repo_type: str = "model") -> Callable[[T], T]:
    """
    Test decorator to create a repo for the test and properly delete it afterward.

    Example:
    ```py
    from openmind_hub import RepoUrl
    from tests.functional.testing_constants import use_tmp_repo

    class TestOmModel(OmApiCommonTest):
        @use_tmp_repo()
        def test_model_info(self, repo_url: RepoUrl):
            (...)
    ```
    """

    def _inner_use_tmp_repo(test_fn: T) -> T:
        @wraps(test_fn)
        def _inner(*args, **kwargs):
            self = args[0]
            if not isinstance(self, unittest.TestCase):
                raise TypeError("Expected a unittest.TestCase instance")

            repo_url = self.api.create_repo(repo_id=f"{owner}/{random_repo_name()}", repo_type=repo_type)
            try:
                return test_fn(*args, **kwargs, repo_url=repo_url)
            finally:
                self.api.delete_repo(repo_id=repo_url.repo_id, repo_type=repo_type)

        return _inner

    return _inner_use_tmp_repo


def is_network_ok():
    try:
        openmind_hub.whoami(token=TOKEN)
        return True
    except AccessWhiteListError:
        return False
